perm filename HALFTO.LST[UHF,DEK] blob sn#841410 filedate 1987-06-15 generic text, type T, neo UTF8
  1) HALFTO.WEB[UHF,DEK] and 2) OLDHAL.WEB[UHF,DEK]	6-15-87 23:16	pages 1,1

**** File 1) HALFTO.WEB[UHF,DEK]/1P/9L
1)	C00028 00007	@* The main program.
1)	C00029 00008	@* Index.
1)	C00040 ENDMK
1)	C⊗;
**** File 2) OLDHAL.WEB[UHF,DEK]/1P/9L
2)	C00026 00007	@* The main program.
2)	C00027 00008	@* Index.
2)	C00038 ENDMK
2)	C⊗;
***************


**** File 1) HALFTO.WEB[UHF,DEK]/3P/2L
1)	This program prepares 33-level halftone images for use in \TeX\ files. The
1)	input is assumed to be a sequence of pictures expressed in the form
**** File 2) OLDHAL.WEB[UHF,DEK]/3P/2L
2)	This program prepares 65-level halftone images for use in \TeX\ files. The
2)	input is assumed to be a sequence of pictures expressed in the form
***************


**** File 1) HALFTO.WEB[UHF,DEK]/3P/18L
1)	for 33-level halftones, with ASCII characters |"0"| to |"P"| representing
1)	darkness levels from white to black. The levels are adjusted to compensate
1)	for the idiosyncrasies of Canon {\mc LBP-CX} laser-printing engines.
1)	Two dots are typeset for each pixel of input; hence there are $2m$
1)	``half\/lines'' of $n$-character data in the output.
1)	@ Here's an outline of the entire Pascal program:
**** File 2) OLDHAL.WEB[UHF,DEK]/3P/18L
2)	for 65-level halftones, with ASCII characters |"0"| to |"p"| representing
2)	darkness levels from white to black. The levels are adjusted to compensate
2)	for the idiosyncrasies of Canon {\mc LBP-CX} laser-printing engines.
2)	@ Here's an outline of the entire Pascal program:
***************


**** File 1) HALFTO.WEB[UHF,DEK]/4P/1L
1)	@* The character set.
**** File 2) OLDHAL.WEB[UHF,DEK]/3P/52L
2)	@ It's convenient to declare a macro for incrementation.
2)	@d incr(#) == #←#+1
2)	@* The character set.
***************


**** File 1) HALFTO.WEB[UHF,DEK]/5P/10L
1)	@!v:array [0..max_m,0..max_n] of real; {pixel darknesses, from 0.0 to 1.0}
1)	@!m:integer; {rows |0..m+1| of |v| should contain relevant data}
1)	@!n:integer; {columns |0..n+1| of |v| should contain relevant data}
**** File 2) OLDHAL.WEB[UHF,DEK]/5P/10L
2)	@!v:array [1..max_m,0..max_n] of real; {pixel darknesses, from 0.0 to 1.0}
2)	@!m:integer; {rows |1..m+1| of |v| should contain relevant data}
2)	@!n:integer; {columns |0..n+1| of |v| should contain relevant data}
***************


**** File 1) HALFTO.WEB[UHF,DEK]/5P/24L
1)	program if anomalous values of |m| and~|n| occur. Boundary values are added
1)	at the top, left, right, and bottom in order to provide ``padding'' that
1)	will be convenient in the pixel transformation process. Each boundary value
1)	is equal to one of its adjacent neighbors.
1)	@<Input a picture, or terminate the program@>=
**** File 2) OLDHAL.WEB[UHF,DEK]/5P/24L
2)	program if anomalous values of |m| and~|n| occur.  Extra zeros are added
2)	at the left, right, and bottom in order to provide ``padding'' that will
2)	be convenient in the pixel transformation process.
2)	@<Input a picture, or terminate the program@>=
***************


**** File 1) HALFTO.WEB[UHF,DEK]/5P/36L
1)		v[i,0]:=v[i,1]; v[i,n+1]:=v[i,n];@/
1)		read_ln;
1)		end;
1)	for j:=0 to n+1 do
1)		begin v[0,j]:=v[1,j]; v[m+1,j]:=v[m,j];
1)		end
1)	@ The code just written makes use of three temporary registers that must
**** File 2) OLDHAL.WEB[UHF,DEK]/5P/35L
2)		v[i,0]:=0.0; v[i,n+1]:=0.0;@/
2)		read_ln;
2)		end;
2)	for j:=0 to n+1 do v[m+1,j]:=0.0
2)	@ The code just written makes use of three temporary registers that must
***************


**** File 1) HALFTO.WEB[UHF,DEK]/6P/1L
1)	@* Pixel compensation.
1)	The 33-level output of this program is assumed to be printed by a font
1)	that contains $4\times8$ characters, where each character has 0 to~32
1)	black bits. Physical properties of output devices cause distortions,
1)	so that a character with |k| black bits does not have an apparent
1)	density of |k/32|. We therefore maintain a table of apparent density
1)	values.
1)	@d max_l=32 {maximum output level}
1)	@<Glob...@>=
**** File 2) OLDHAL.WEB[UHF,DEK]/5P/46L
2)	@!cc:ASCII_code; {ASCII equivalent of |c|}
2)	@* Pixel compensation.
2)	The 65-level output of this program is assumed to be printed by a font
2)	that contains $8\times8$ characters, where each character has 0 to~64
2)	black bits. Physical properties of output devices cause distortions,
2)	so that a character with |k| black bits does not have an apparent
2)	density of |k/64|. We therefore maintain a table of apparent density
2)	values.
2)	@d max_l=64 {maximum output level}
2)	@<Glob...@>=
***************


**** File 1) HALFTO.WEB[UHF,DEK]/6P/16L
1)	a page and the bottom; also blocks of the character |"N"| seem to appear
1)	darker than blocks of the character |"O"|, because of some property of
1)	xerography, although the |"O"| has one more bit turned on. Such
1)	anomalies have been smoothed out here, since the resulting values should
**** File 2) OLDHAL.WEB[UHF,DEK]/6P/16L
2)	a page and the bottom; also blocks of character |"n"| seem to appear
2)	darker than blocks of the character |"o"|, because of some property of
2)	xerography, although the |"o"| has one more bit turned on. Such
2)	anomalies have been smoothed out here, since the resulting values should
***************


**** File 1) HALFTO.WEB[UHF,DEK]/6P/24L
1)	d[1]:=0.06;
1)	d[2]:=0.095;
1)	d[3]:=0.125;
1)	d[4]:=0.155;@/
1)	d[5]:=0.175;
1)	d[6]:=0.215;
1)	d[7]:=0.245;
1)	d[8]:=0.27;
1)	d[9]:=0.29;@/
1)	d[10]:=0.3;
1)	d[11]:=0.31;
1)	d[12]:=0.32;
1)	d[13]:=0.33;
1)	d[14]:=0.34;@/
1)	d[15]:=0.35;
1)	d[16]:=0.36;
1)	d[17]:=0.37;
1)	d[18]:=0.38;
1)	d[19]:=0.4;@/
1)	d[20]:=0.42;
1)	d[21]:=0.44;
1)	d[22]:=0.47;
1)	d[23]:=0.5;
1)	d[24]:=0.53;@/
1)	d[25]:=0.57;
1)	d[26]:=0.61;
1)	d[27]:=0.66;
1)	d[28]:=0.72;
1)	d[29]:=0.80;@/
1)	d[30]:=0.88;
1)	d[31]:=0.96;
1)	d[32]:=1.0;
1)	@ We convert the pixel values by using a variant of the Floyd-Steinberg
**** File 2) OLDHAL.WEB[UHF,DEK]/6P/24L
2)	d[1]:=0.03;
2)	d[2]:=0.06;
2)	d[3]:=0.08;
2)	d[4]:=0.095;@/
2)	d[5]:=0.11;
2)	d[6]:=0.125;
2)	d[7]:=0.14;
2)	d[8]:=0.155;
2)	d[9]:=0.17;@/
2)	d[10]:=0.175;
2)	d[11]:=0.2;
2)	d[12]:=0.215;
2)	d[13]:=0.23;
2)	d[14]:=0.245;@/
2)	d[15]:=0.26;
2)	d[16]:=0.27;
2)	d[17]:=0.28;
2)	d[18]:=0.29;
2)	d[19]:=0.295;@/
2)	d[20]:=0.3;
2)	d[21]:=0.305;
2)	d[22]:=0.31;
2)	d[23]:=0.315;
2)	d[24]:=0.32;@/
2)	d[25]:=0.325;
2)	d[26]:=0.33;
2)	d[27]:=0.335;
2)	d[28]:=0.34;
2)	d[29]:=0.345;@/
2)	d[30]:=0.35;
2)	d[31]:=0.355;
2)	d[32]:=0.36;
2)	d[33]:=0.365;
2)	d[34]:=0.37;@/
2)	d[35]:=0.375;
2)	d[36]:=0.38;
2)	d[37]:=0.39;
2)	d[38]:=0.4;
2)	d[39]:=0.41;@/
2)	d[40]:=0.42;
2)	d[41]:=0.43;
2)	d[42]:=0.44;
2)	d[43]:=0.455;
2)	d[44]:=0.47;@/
2)	d[45]:=0.485;
2)	d[46]:=0.5;
2)	d[47]:=0.515;
2)	d[48]:=0.53;
2)	d[49]:=0.55;@/
2)	d[50]:=0.57;
2)	d[51]:=0.59;
2)	d[52]:=0.61;
2)	d[53]:=0.635;
2)	d[54]:=0.66;@/
2)	d[55]:=0.685;
2)	d[56]:=0.71;
2)	d[57]:=0.74;
2)	d[58]:=0.77;
2)	d[59]:=0.8;@/
2)	d[60]:=0.84;
2)	d[61]:=0.88;
2)	d[62]:=0.92;
2)	d[63]:=0.96;
2)	d[64]:=1.0;
2)	@ We convert the pixel values by using a variant of the Floyd-Steinberg
***************


**** File 1) HALFTO.WEB[UHF,DEK]/6P/66L
1)	in column~|j| of the current half\/line.
1)	It outputs one 33-level density,
1)	then updates |x| and~|j| in preparation for the next column.
1)	Adjustments to the densities in the two next half\/lines are
1)	accumulated in auxiliary arrays |next1| and |next2|; this will compensate
1)	for errors in the current half\/line.
1)	We assume that |next1[j]|, |next1[j+1]|, and |next2[j]| correspond to the
1)	dots that are adjacent to |current[j]|.
1)	@<Output one value and move to the next column@>=
**** File 2) OLDHAL.WEB[UHF,DEK]/6P/98L
2)	in row~|i| and column~|j|. It outputs one 65-level density,
2)	then updates |x| and~|j| in preparation for the next column in row~|i|.
2)	Pixel values in row~|i+1| are modified to compensate for errors in
2)	the current row.
2)	@<Output one value and move to the next column@>=
***************


**** File 1) HALFTO.WEB[UHF,DEK]/6P/79L
1)	next1[j]:=next1[j]+alpha*err;@/
1)	next2[j]:=beta*err;@/
1)	j←j+1; {move right}
1)	next1[j]:=next1[j]+gamma*err;@/
1)	x:=current[j]+delta*err
1)	@ The constants |alpha..delta| control the distribution of errors to
1)	adjacent dot positions.
1)	@<Set init...@>=
1)	alpha:=7/16; {error diffusion to SW neighbor}
1)	beta:=1/16; {error diffusion to S neighbor}
1)	gamma:=5/16; {error diffusion to SE neighbor}
1)	delta:=3/16; {error diffusion to E neighbor}
1)	@ Here is the overall control of the process.
1)	Every half\/line of the picture being output is a sequence of ASCII characters
1)	from |"0"| to |"P"|, terminated by |"."|.
1)	@<Output the picture@>=
1)	for j:=1 to n+1 do
1)		begin next1[j]:=0.0; next2[j]:=0.0;
1)		end;
1)	for i:=1 to m do
1)		begin @<Set the current half\/line data for the upper row of dots in line~|i|@>;
1)		j:=1; x:=current[1];
1)		repeat @<Output one value...@>;
**** File 2) OLDHAL.WEB[UHF,DEK]/6P/106L
2)	v[i+1,j-1]:=v[i+1,j-1]+alpha*err;@/
2)	v[i+1,j]:=v[i+1,j]+beta*err;@/
2)	incr(j); {move right}
2)	v[i+1,j]:=v[i+1,j]+gamma*err;@/
2)	x:=v[i,j]+delta*err
2)	@ Here is the overall control of the process.
2)	Every line of the picture is a sequence of ASCII characters from |"0"| to |"p"|,
2)	terminated by |"."|.
2)	@<Output the picture@>=
2)	for i:=1 to m do
2)		begin j:=1; x:=v[i,1];
2)		repeat @<Output one value...@>;
***************


**** File 1) HALFTO.WEB[UHF,DEK]/6P/108L
1)		@<Set the current half\/line data for the lower row of dots in line~|i|@>;
1)		j:=1; x:=current[1];
1)		repeat @<Output one value...@>;
1)		until j>n;
1)		write_ln('.');
1)		end
1)	@ The density value for dot |j| in the upper half\/line of line~|i| is obtained
1)	as a weighted average of the input values in rows |i-1| and~|i|, columns
1)	|j| and~|j+1|. The upper half\/line is skewed to the right, so we must shift
1)	|next1| and |next2| appropriately.
1)	@<Set the current half\/line data for the upper row of dots in line~|i|@>=
1)	for j←1 to n do
1)		begin current[j]←(9*v[i,j]+3*v[i,j+1]+3*v[i-1,j]+v[i-1,j+1])/16
1)			+next1[j+1];
1)		next1[j]←next2[j];
1)		end;
1)	next1[n+1]←0.0
1)	@ The lower half\/line is similar, but in this case there is leftward skew;
1)	we use rows |i| and~|i+1|, columns |j-1| and~|j|.
1)	@<Set the current half\/line data for the lower row of dots in line~|i|@>=
1)	for j←1 to n do
1)		begin current[j]←(9*v[i,j]+3*v[i,j-1]+3*v[i+1,j]+v[i+1,j-1])/16
1)			+next1[j];
1)		next1[j+1]←next2[j];
1)		end;
1)	next1[1]←0.0
1)	@ The algorithm is now complete except for the part that chooses the
1)	closest possible dot size. A straightforward binary search works well
1)	for this purpose:
1)	@<Find |l| so that |d[l]| is as close as possible to |x|@>=
**** File 2) OLDHAL.WEB[UHF,DEK]/6P/122L
2)		end
2)	@ It turns out to be desirable to
2)	throw away about 10\% of the error. This dampens ``history'' effects
2)	that the algorithm might otherwise introduce.
2)	@<Set init...@>=
2)	alpha:=3/18; {error diffusion to SW neighbor}
2)	beta:=5/18; {error diffusion to S neighbor}
2)	gamma:=1/18; {error diffusion to SE neighbor}
2)	delta:=7/18; {error diffusion to E neighbor}
2)	@ Here we use a straightforward binary search.
2)	@<Find |l| so that |d[l]| is as close as possible to |x|@>=
***************


**** File 1) HALFTO.WEB[UHF,DEK]/6P/160L
1)	@!current:array[0..max_n] of real; {desired densities in current half\/line}
1)	@!next1,@!next2:array[0..max_n] of real; {corrections to subsequnt densities}
1)	@!alpha,@!beta,@!gamma,@!delta:real; {constants of error diffusion}
**** File 2) OLDHAL.WEB[UHF,DEK]/6P/153L
2)	@!alpha,@!beta,@!gamma,@!delta:real; {constants of error diffusion}
***************


**** File 1) HALFTO.WEB[UHF,DEK]/7P/5L
1)	write_ln('\input hf33'); write_ln;
1)	while true do
**** File 2) OLDHAL.WEB[UHF,DEK]/7P/5L
2)	write_ln('\input halftone'); write_ln;
2)	while true do
***************